#include "ModelSerializer.h"
#include <SEngine/Render/Entity/Model.h>
#include <yaml-cpp/yaml.h>
#include <SESerializeYAML/Util.h>
#include <SEDebug/Log/Log.h>
#include <SECore/Manager.h>

namespace SEngine
{
    std::string Serializer<Model>::Serialize(Model & object)
    {
        YAML::Node node;
        node["Model"]["MeshFilter"] = !object.m_meshFilter ? "" : object.m_meshFilter.Name();
        object.ForeachMaterialFilter([&](std::string name, ResRef<Material> & material) {
            YAML::Node materialNode;
            materialNode["Mesh"] = name;
            materialNode["Material"] = !material ? "" : material.Name();
            node["Model"]["Materials"].push_back(materialNode);
        });
        return YAMLNodeToString(node);
    }

    void Serializer<Model>::Deserialize(const std::string& str, Model & object)
    {
        try {
            YAML::Node node = YAML::Load(str);
            auto meshFilter = node["Model"]["MeshFilter"].as<std::string>();
            if (!meshFilter.empty()) {
                object.SetMeshFilter(Manager::GetInstance().Get<MeshFilter>(meshFilter).value(), Manager::GetInstance().Get<Material>("Standard").value());
            }
            for (auto & materialNode : node["Model"]["Materials"]) {
                auto meshName = materialNode["Mesh"].as<std::string>();
                auto materialName = materialNode["Material"].as<std::string>();
                object.SetMaterial(meshName, Manager::GetInstance().Get<Material>(materialName).value());
            }
        } catch(const std::exception& e) {
            Log::GetInstance().Warn("Model Deserialize: {}", e.what());
        }
    }
} // namespace SEngine
